﻿using Microsoft.VisualBasic.Devices;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;


using UCore;

namespace Twin {
    public partial class BinView : Form {

        private const int RowsPerPage = 24;
        private const int MaxRetries = 3;
        private const int RetryDelay = 100;

        private long currentPage = 0;
        private long maxPage = 0;
        private long fileSize = 0;
        private int selectedRow = 0;

        private HexViewInfo hvi;

        private string fn_hex_source;
        private string fn_comment;
        private int BytesPerRow;

        private int memory_type;
        private XME Xme;
        private XCX currentXcx; // 新增XCX实例

        private XPort xport = new XPort();

        private string[] arg = new string[4];
        //
        private int INST_BITS = 0;
        private int INST_OP = 1;
        private int INST_CMFG = 2;
        private int INST_INSTANT = 3;


        public class LineData {
            public DateTime Time { get; set; }
            public string TimeDisplay { get; set; }
            public string Comment { get; set; }
            public string Address { get; set; }
            public string Bytes { get; set; }
            public string Ascii { get; set; }
        }


        private void addPanel(int M_type) {
            panelMASS.Visible = false;
            panelMEM.Visible = false;

            switch (M_type) {
                case Ini.M_MEM:
                    panelMEM.Visible = true;
                    break;
                
                case Ini.M_MASS:
                    panelMASS.Visible = true;
                    Xme = new XME(Ini.size_of.elem);
                    int nXCX = UI.init_cmbXcx(cmbXCX);
                    break;
            }
        }


        public BinView(int M_type, XPort xport) {
            InitializeComponent();

            // 订阅全局数据解析事件
            Worker.OnDataParsed += HandleParsedData;
            
            this.xport = xport;


            // Add this line to connect the event handler
            dgv.SelectionChanged += dataGridView_SelectionChanged;

            hvi = new HexViewInfo(M_type);
            BytesPerRow = hvi.BytesPerLine;
            fn_hex_source = Ini.dir_io_file + "\\" + hvi.fn_hex_source;
            fn_comment = Ini.dir_io_file + "\\" + hvi.fn_comment;

            this.KeyPreview = true;                     // 添加此行以启用键盘事件预览
            this.KeyDown += BinView_KeyDown;            // 确保事件处理程序已绑定（部分情况可能需要）
            this.FormClosing += BinView_FormClosing;    // 添加事件绑定

            memory_type = M_type;
            addPanel(memory_type);

            // 初始化右侧分析文本框
            txtAnalysis.Multiline = true;
            txtAnalysis.ScrollBars = ScrollBars.Vertical;
            txtAnalysis.ReadOnly = true;
            txtAnalysis.Font = new Font("Consolas", 9.75f);
            txtAnalysis.Dock = DockStyle.None; // 禁用Dock模式
            this.Controls.Add(txtAnalysis);

            cmbXCX.Font = new Font("Consolas", 13f);    // 9.75f);
        }


        private void AdjustDataGridViewSize() {
            const int analysisWidth = 260; // Fixed width for right panel
            const int padding = 10;        // Margin between controls

            // Calculate total width of all columns
            int totalColumnsWidth = dgv.Columns
                .Cast<DataGridViewColumn>()
                .Sum(c => c.Width);

            // Add extra space for row headers and vertical scrollbar
            totalColumnsWidth += dgv.RowHeadersWidth;
            if (dgv.ScrollBars.HasFlag(ScrollBars.Vertical)) {
                totalColumnsWidth += SystemInformation.VerticalScrollBarWidth;
            }

            // Ensure we don't exceed available form width
            int maxAvailableWidth = this.ClientSize.Width - analysisWidth - (padding * 3);
            totalColumnsWidth = Math.Min(totalColumnsWidth, maxAvailableWidth);

            // Set DataGridView dimensions
            dgv.Location = new Point(padding, padding);
            dgv.Width = totalColumnsWidth - 13;    //微调
            dgv.Height = this.ClientSize.Height - padding * 2 - 21;    //微调 35;

            // Position the analysis panel
            txtAnalysis.Location = new Point(
                dgv.Right + padding,
                dgv.Top
            );
            txtAnalysis.Width = analysisWidth;
            txtAnalysis.Height = dgv.Height;

            // Set anchoring
            dgv.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Bottom;
            txtAnalysis.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Right;
        }


        private async void BinView_Load(object sender, EventArgs e) {
            InitializeDataGridView();
            AdjustDataGridViewSize(); // 初始化时调整大小
   
            txtMassPtr.Font = new Font("Consolas", 11.75f);

            if (memory_type == Ini.M_MEM) { 
                txtAnalysis.Width -= 35;
            }

            currentXcx = new XCX();

            await InitializeFileInfo();
            LoadSettings();

            // 新增：限制当前页不超过最大有效页
            currentPage = Math.Max(0, Math.Min(maxPage - 1, currentPage));

            await LoadPage();
        }


        private void InitializeDataGridView() {
            // Set default font for the entire DataGridView
            dgv.DefaultCellStyle.Font = new Font("SimHei", 10.5f, FontStyle.Bold);
            dgv.ColumnHeadersDefaultCellStyle.Font = new Font("SimHei", 10.5f, FontStyle.Bold);

            switch (memory_type) {
                case Ini.M_MEM:
                    InitializeDataGridView_MEM();
                    break;

                case Ini.M_MASS:
                    InitializeDataGridView_MASS();
                    break;
            }
        }


        private void InitializeDataGridView_MEM() {
            dgv.AutoGenerateColumns = false;
            dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            dgv.ReadOnly = true;
            dgv.AllowUserToAddRows = false;  // 添加这行以移除空白行

            // 新增最左侧列（例如行号列）
            DataGridViewTextBoxColumn commentColumn = new DataGridViewTextBoxColumn {
                HeaderText = "#", // 列标题
                DataPropertyName = "Comment",
                Name = "Comment", // 列名称
                Width = 125 // 宽度
            };

            DataGridViewTextBoxColumn addrColumn = new DataGridViewTextBoxColumn {
                HeaderText = "  addr",
                DataPropertyName = "Address",
                Name = "Address",
                Width = 85,
                DefaultCellStyle = new DataGridViewCellStyle {
                    Alignment = DataGridViewContentAlignment.MiddleCenter   //MiddleRight
                }
            };

            DataGridViewTextBoxColumn bytesColumn = new DataGridViewTextBoxColumn {
                HeaderText = hvi.bytesColumnStr,       //"0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F ",
                DataPropertyName = "Bytes",
                Name = "Bytes",
                Width = 405,
                DefaultCellStyle = new DataGridViewCellStyle {
                    Alignment = DataGridViewContentAlignment.MiddleCenter   //MiddleRight
                }
            };

            DataGridViewTextBoxColumn asciiColumn = new DataGridViewTextBoxColumn {
                HeaderText = "      ASCII",
                DataPropertyName = "Ascii",
                Name = "Ascii",
                Width = 160,
                DefaultCellStyle = new DataGridViewCellStyle {
                    Alignment = DataGridViewContentAlignment.MiddleCenter   //MiddleRight
                }
            };

            dgv.Columns.AddRange(commentColumn, addrColumn, bytesColumn, asciiColumn);

            // 在 InitializeDataGridView() 的最后添加：
            dgv.Columns["Comment"].DisplayIndex = 0;  // 强制设为第一列
            dgv.Columns["Address"].DisplayIndex = 1;
            dgv.Columns["Bytes"].DisplayIndex = 2;
            dgv.Columns["Ascii"].DisplayIndex = 3;
        }


        private void InitializeDataGridView_MASS() { 
            dgv.AutoGenerateColumns = false;
            dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            dgv.ReadOnly = true;
            dgv.AllowUserToAddRows = false;  // 添加这行以移除空白行

            // 添加时间列
            DataGridViewTextBoxColumn timeColumn = new DataGridViewTextBoxColumn {
                HeaderText = "Time",
                DataPropertyName = "TimeDisplay",
                Name = "Time",
                Width = 180,
                DefaultCellStyle = new DataGridViewCellStyle {
                    Alignment = DataGridViewContentAlignment.MiddleRight
                }
            };

            DataGridViewTextBoxColumn addrColumn = new DataGridViewTextBoxColumn {
                HeaderText = "   addr",
                DataPropertyName = "Address",
                Name = "Address",
                Width = 100,
                DefaultCellStyle = new DataGridViewCellStyle {
                    Alignment = DataGridViewContentAlignment.MiddleCenter   //MiddleRight
                }
            };

            DataGridViewTextBoxColumn bytesColumn = new DataGridViewTextBoxColumn {
                HeaderText = "       " + hvi.bytesColumnStr,       //"0  1  2  3  4  5  6  7",
                DataPropertyName = "Bytes",
                Name = "Bytes",
                Width = 300,
                DefaultCellStyle = new DataGridViewCellStyle {
                    Alignment = DataGridViewContentAlignment.MiddleCenter   //MiddleRight
                }
            };

            DataGridViewTextBoxColumn asciiColumn = new DataGridViewTextBoxColumn {
                HeaderText = "      ASCII",
                DataPropertyName = "Ascii",
                Name = "Ascii",
                Width = 120,
                DefaultCellStyle = new DataGridViewCellStyle {
                    Alignment = DataGridViewContentAlignment.MiddleCenter   //MiddleRight
                }
            };

            dgv.Columns.AddRange(timeColumn, addrColumn, bytesColumn, asciiColumn);

            // 在 InitializeDataGridView() 的最后添加：
            dgv.Columns["Time"].DisplayIndex = 0;  // 强制设为第一列
            dgv.Columns["Address"].DisplayIndex = 1;
            dgv.Columns["Bytes"].DisplayIndex = 2;
            dgv.Columns["Ascii"].DisplayIndex = 3;

            // 为所有列设置可聚焦属性
            foreach (DataGridViewColumn column in dgv.Columns) {
                column.SortMode = DataGridViewColumnSortMode.NotSortable;
                column.DefaultCellStyle.BackColor = Color.White;
                column.DefaultCellStyle.SelectionBackColor = SystemColors.Highlight;
            }

            // 允许单元格获得焦点
            dgv.StandardTab = true;
            dgv.EditMode = DataGridViewEditMode.EditProgrammatically;
        }


        private async Task InitializeFileInfo() {
            FileInfo fi = new FileInfo(fn_hex_source);
            while (true) {
                try {
                    using (FileStream fs = new FileStream(fn_hex_source, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                        switch (memory_type) {
                            case Ini.M_MEM:
                                currentXcx.top = 0;
                                currentXcx.bottom = fs.Length;
                                break;

                            case Ini.M_MASS:
                                int iXcx = cmbXCX.SelectedIndex;
                                currentXcx = Xme.Xcx[iXcx];
                                break;
                        }

                        // 修改为使用XCX的区间计算文件大小
                        long rangeSize = currentXcx.bottom - currentXcx.top;
                        fileSize = Math.Min(rangeSize, fs.Length - currentXcx.top);
                        //fileSize = fs.Length;

                        maxPage = (fileSize + (RowsPerPage * BytesPerRow) - 1) / (RowsPerPage * BytesPerRow);
                        return;
                    }
                } catch (IOException) {
                    if (MessageBox.Show("文件被锁定，重试？", "错误", MessageBoxButtons.RetryCancel) != DialogResult.Retry)
                        Close();
                    await Task.Delay(RetryDelay);
                }
            }
        }


        private async Task<byte[]> ReadWithRetry(long offset, int bytesToRead) {
            for (int i = 0; i < MaxRetries; i++) {
                try {
                    using (FileStream fs = new FileStream(fn_hex_source, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                        fs.Seek(offset, SeekOrigin.Begin);
                        byte[] buffer = new byte[bytesToRead];
                        int bytesRead = await fs.ReadAsync(buffer, 0, bytesToRead);
                        Array.Resize(ref buffer, bytesRead);
                        return buffer;
                    }
                } catch (IOException) {
                    if (i == MaxRetries - 1) throw;
                    await Task.Delay(RetryDelay);
                }
            }
            return new byte[0];
        }


        //转换：
        //00006030 = FSL6510 不变
        //0000626E = MIR_STATUS  => 00006260 = MIR_STATUS[E]
        //Dictionary结果： address : comment
        private Dictionary<string, string> LoadComments() {
            var comments = new Dictionary<string, string>();
            string commentFilePath = Path.Combine(Ini.dir_io_file, hvi.fn_comment);     // "_MEM_32K_comments.txt");

            if (File.Exists(commentFilePath)) {
                foreach (var line in File.ReadAllLines(commentFilePath)) {
                    var parts = line.Split('=');
                    if (parts.Length == 2) {
                        string k = parts[0].Trim().ToUpper();
                        string c = k.Substring(k.Length - 1);
                        if (k.EndsWith("0")) {
                            comments[k] = parts[1].Trim();
                        } else {
                            k = k.Substring(0, k.Length - 1) + "0"; //
                            comments[k] = parts[1].Trim() + "[" + c + "]";
                        }
                    }
                }
            }
            return comments;
        }


        //Dictionary结果： comment : address 
        private Dictionary<string, string> LoadAddress() {
            var address = new Dictionary<string, string>();
            string commentFilePath = Path.Combine(Ini.dir_io_file, hvi.fn_comment);    

            if (File.Exists(commentFilePath)) {
                foreach (var line in File.ReadAllLines(commentFilePath)) {
                    var parts = line.Split('=');
                    if (parts.Length == 2) {
                        string k = parts[1].Trim().ToUpper();
                        //string c = k.Substring(k.Length - 1);
                        //if (k.EndsWith("0")) {
                            address[k] = parts[0].Trim();
                        
                    }
                }
            }
            return address;
        }


        private List<LineData> ParseData(byte[] buffer, long baseOffset) {

            switch (memory_type) {
                case Ini.M_MEM:
                    return ParseData_MEM(buffer, baseOffset);
                    break;

                case Ini.M_MASS:
                    return ParseData_MASS(buffer, baseOffset);
                    //break;
            }
            return null;
        }


        private List<LineData> ParseData_MEM(byte[] buffer, long baseOffset) {
            var comments = LoadComments();
            var lines = new List<LineData>();

            for (int i = 0; i < buffer.Length; i += BytesPerRow) {
                long address = baseOffset + i;
                // 确保不超过XCX.bottom
                if (address >= currentXcx.bottom) break;

                string hexAddress = address.ToString("X8");
                byte[] rowData = buffer.Skip(i).Take(BytesPerRow).ToArray();

                lines.Add(new LineData {
                    Comment = comments.TryGetValue(hexAddress, out var comment) ? comment : "",
                    Address = hexAddress,
                    Bytes = BitConverter.ToString(rowData).Replace("-", " "),
                    Ascii = new string(rowData.Select(b => b >= 0x20 && b <= 0x7E ? (char)b : '.').ToArray())
                });
            }
            return lines;
        }


        private List<LineData> ParseData_MASS(byte[] buffer, long baseOffset) { 
            var lines = new List<LineData>();
            DateTime? prevTime = null;

            // 获取基准时间
            DateTime baseTime = new DateTime(
                currentXcx.year + 2000,
                currentXcx.month,
                currentXcx.day,
                currentXcx.hour, 0, 0);

            // 获取元素信息
            ELEMENT e = Xme.Els.element[currentXcx.iCx];

            for (int i = 0; i < buffer.Length; i += BytesPerRow) {
                int rowInPage = i / BytesPerRow;

                // 根据单位类型计算时间偏移量
                TimeSpan timeOffset;
                switch (e.UNIT) {
                    case 0: // 秒
                        timeOffset = TimeSpan.FromSeconds(e.XmeGrid * (currentPage * RowsPerPage + rowInPage));
                        break;
                    case 1: // 分钟
                        timeOffset = TimeSpan.FromMinutes(e.XmeGrid * (currentPage * RowsPerPage + rowInPage));
                        break;
                    case 2: // 小时
                        timeOffset = TimeSpan.FromHours(e.XmeGrid * (currentPage * RowsPerPage + rowInPage));
                        break;
                    case 3: // 天
                        timeOffset = TimeSpan.FromDays(e.XmeGrid * (currentPage * RowsPerPage + rowInPage));
                        break;
                    default: // 默认按分钟计算
                        timeOffset = TimeSpan.FromMinutes(e.XmeGrid * (currentPage * RowsPerPage + rowInPage));
                        break;
                }

                DateTime currentTime = baseTime.Add(timeOffset);

                string timeDisplay;
                if (rowInPage == 0) {
                    timeDisplay = currentTime.ToString("yyyy-MM-dd HH:mm:ss");
                } else {
                    timeDisplay = GetSimplifiedDisplay(prevTime.Value, currentTime);
                }
				
                long address = baseOffset + i;
                // 确保不超过XCX.bottom
                if (address >= currentXcx.bottom) break;

                string hexAddress = address.ToString("X8");
                byte[] rowData = buffer.Skip(i).Take(BytesPerRow).ToArray();
                lines.Add(new LineData {
                    Time = currentTime,
                    TimeDisplay = timeDisplay,
                    // 其他属性赋值...
                    //Comment = comments.TryGetValue(hexAddress, out var comment) ? comment : "",
                    Address = hexAddress,
                    Bytes = BitConverter.ToString(rowData).Replace("-", " "),
                    Ascii = new string(rowData.Select(b => b >= 0x20 && b <= 0x7E ? (char)b : '.').ToArray())
                });

                prevTime = currentTime;
            }
            return lines;
        }


        private string GetSimplifiedDisplay(DateTime prev, DateTime current) {
            if (prev == current) return new string(' ', 19);

            var parts = new Dictionary<string, (Func<DateTime, int> getPart, int index)> {
        { "Year", (d => d.Year, 0) },
        { "Month", (d => d.Month, 5) },
        { "Day", (d => d.Day, 8) },
        { "Hour", (d => d.Hour, 11) },
        { "Minute", (d => d.Minute, 14) },
        { "Second", (d => d.Second, 17) }
    };

            int replaceIndex = 19;
            foreach (var part in parts) {
                if (part.Value.getPart(prev) != part.Value.getPart(current)) {
                    replaceIndex = part.Value.index;
                    break;
                }
            }

            char[] display = current.ToString("yyyy-MM-dd HH:mm:ss").ToCharArray();
            for (int i = 0; i < replaceIndex; i++) {
                display[i] = ' ';
            }
            return new string(display);
        }


        // 错误：行焦点改变时，没有触发进入以下事件
        private void dataGridView_SelectionChanged(object sender, EventArgs e) {
            if (dgv.SelectedRows.Count == 0) return;

            selectedRow = dgv.SelectedRows[0].Index;
            var line = (LineData)dgv.SelectedRows[0].DataBoundItem;

            // 更新右侧分析面板
            txtAnalysis.Text = BuildAnalysisText(line);
        }


        private string BuildAnalysisText(LineData line) {
            // 示例格式化代码
            return $@"[地址] {line.Address}
[原始数据] {line.Bytes}
[ASCII] {line.Ascii}
{AnalyzeBytes(line.Bytes)}";
        }

        private string AnalyzeBytes(string hexString) {
            // 添加您的自定义解析逻辑
            return $"解析结果：{hexString}";
        }


        private void BinView_KeyDown(object sender, KeyEventArgs e) {
            switch (e.KeyCode) {
                case Keys.PageUp:
                    currentPage = Math.Max(0, currentPage - 1);
                    _ = LoadPage();
                    e.Handled = true; // 可选，标记事件已处理
                    break;
                case Keys.PageDown:
                    // 修正：直接使用maxPage作为上限
                    currentPage = Math.Min(maxPage - 1, currentPage + 1);
                    //currentPage = Math.Min(maxPage - 1, currentPage + 1); // 修正maxPage使用
                    _ = LoadPage();
                    e.Handled = true;
                    break;
            }
        }


        private void LoadSettings() {
            currentPage = int.Parse(Ini.iniDictionary["_MEM_32K"]["current_page"]);    //Ini.iniDictionary["Info"]["FileSn"];//Properties.Settings.Default.LastPage;
            selectedRow = int.Parse(Ini.iniDictionary["_MEM_32K"]["selected_row"]);    //Properties.Settings.Default.LastRow;
        }

        
        private void SaveSettings() {
            //Properties.Settings.Default.LastPage = currentPage;
            //Properties.Settings.Default.LastRow = selectedRow;
            //Properties.Settings.Default.Save();
            Ini.WriteKeyValue(Ini.path_Console_ini, "_MEM_32K.current_page", currentPage.ToString());
            Ini.WriteKeyValue(Ini.path_Console_ini, "_MEM_32K.selected_row", selectedRow.ToString());
        }


        private void BinView_FormClosing(object sender, FormClosingEventArgs e) {
            // 取消订阅防止内存泄漏
            Worker.OnDataParsed -= HandleParsedData;
            SaveSettings();
        }


        private void HandleParsedData(string sNow){   
            // 确保UI线程操作
            if (this.InvokeRequired) {
                this.BeginInvoke(new Action(() => HandleParsedData(sNow)));   // parsedData)));
                return;
            }

            // 根据命令类型处理数据
            //if (parsedData.TryGetValue("command", out object cmd) && cmd.ToString() == "OP_RD_INS") {
                UpdateUIWithData(sNow);
            //}
        }


        //private void UpdateUIWithData(string sNow) {
        //    // 解析为 DateTime（自动处理日期时间格式）
        //    DateTime nowDateTime = DateTime.Parse(sNow);

        //    // 更新时间显示
        //    txtMassPtr.Text = sNow;

        //    请完成以下代码：{
        //        if (sNow < currentXcx.top对应的时间) {
        //            txtMassPtr.Text = "<" + txtMassPtr.Text;
        //            底色变红
        //        }

        //        if (sNow > currentXcx.bottom对应的时间) {
        //            txtMassPtr.Text = ">" + txtMassPtr.Text;
        //            底色变红
        //        }

        //        与Time列最接近的时间处，第一列置为"->"，并设置为焦点
        //    }

        //    //if (data.TryGetValue("time", out object timeObj) && timeObj is DateTime) {
        //    //    txtMassPtr.Text = $"最后接收: {((DateTime)timeObj):HH:mm:ss}";
        //    //}

        //    //// 更新具体数据（示例：显示寄存器值）
        //    //if (data.TryGetValue("value", out object valueObj) && valueObj is short) {
        //    //    txtAnalysis.AppendText($"寄存器值: 0x{((short)valueObj):X4}\r\n");
        //    //}

        //    // 触发界面重绘
        //    dgv.Refresh();
        //}

        private void UpdateUIWithData(string sNow) {
            // 解析为 DateTime（自动处理日期时间格式）
            DateTime nowDateTime = DateTime.Parse(sNow);

            // 更新时间显示
            txtMassPtr.Text = sNow;

            // 获取当前XCX的时间范围
            DateTime baseTime = new DateTime(
                currentXcx.year + 2000,
                currentXcx.month,
                currentXcx.day,
                currentXcx.hour, 0, 0);

            // 获取元素信息
            ELEMENT e = Xme.Els.element[currentXcx.iCx];

            // 计算时间范围
            DateTime startTime = baseTime;
            DateTime endTime = CalculateEndTime(baseTime, e);

            // 检查时间是否超出范围并设置样式
            if (nowDateTime < startTime) {
                txtMassPtr.Text = "<" + txtMassPtr.Text;
                txtMassPtr.BackColor = Color.LightCoral;
            } else if (nowDateTime > endTime) {
                txtMassPtr.Text = ">" + txtMassPtr.Text;
                txtMassPtr.BackColor = Color.LightCoral;
            } else {
                txtMassPtr.BackColor = SystemColors.Window;
            }

            // 查找最接近的时间行
            int closestRowIndex = FindClosestTimeRow(nowDateTime, e, baseTime);

            if (closestRowIndex >= 0) {
                // 清除所有行的标记
                foreach (DataGridViewRow row in dgv.Rows) {
                    if (!row.IsNewRow && row.Cells.Count > 0 && row.Cells[0].Value != null) {
                        string cellValue = row.Cells[0].Value.ToString();
                        if (cellValue.EndsWith("->")) {
                            row.Cells[0].Value = cellValue.Replace("->", "");
                        }
                    }
                }

                // 标记目标行
                if (dgv.Rows[closestRowIndex].Cells.Count > 0) {
                    string currentValue = dgv.Rows[closestRowIndex].Cells[0].Value?.ToString() ?? "";
                    dgv.Rows[closestRowIndex].Cells[0].Value = currentValue + "->";
                }

                // 选中并滚动到该行
                dgv.ClearSelection();
                dgv.Rows[closestRowIndex].Selected = true;
                dgv.FirstDisplayedScrollingRowIndex = closestRowIndex;

                // 设置焦点
                if (dgv.Columns.Count > 0) {
                    DataGridViewColumn firstVisibleColumn = dgv.Columns
                        .Cast<DataGridViewColumn>()
                        .FirstOrDefault(c => c.Visible && c.DisplayIndex >= 0);

                    if (firstVisibleColumn != null) {
                        dgv.CurrentCell = dgv.Rows[closestRowIndex].Cells[firstVisibleColumn.Index];
                        dgv.BeginEdit(false);
                    }
                }
                dgv.Focus();
            }
        }

        private DateTime CalculateEndTime(DateTime baseTime, ELEMENT e) {
            // 计算结束时间
            double totalUnits = (currentXcx.bottom - currentXcx.top) / (double)BytesPerRow;
            TimeSpan timeOffset = TimeSpan.Zero;

            switch (e.UNIT) {
                case 0: timeOffset = TimeSpan.FromSeconds(e.XmeGrid * totalUnits); break;
                case 1: timeOffset = TimeSpan.FromMinutes(e.XmeGrid * totalUnits); break;
                case 2: timeOffset = TimeSpan.FromHours(e.XmeGrid * totalUnits); break;
                case 3: timeOffset = TimeSpan.FromDays(e.XmeGrid * totalUnits); break;
                default: timeOffset = TimeSpan.FromMinutes(e.XmeGrid * totalUnits); break;
            }

            return baseTime.Add(timeOffset);
        }

        private int FindClosestTimeRow(DateTime targetTime, ELEMENT e, DateTime baseTime) {
            if (dgv.Rows.Count == 0) return -1;

            int closestRow = -1;
            TimeSpan minDifference = TimeSpan.MaxValue;

            for (int i = 0; i < dgv.Rows.Count; i++) {
                if (dgv.Rows[i].IsNewRow) continue;

                var lineData = dgv.Rows[i].DataBoundItem as LineData;
                if (lineData == null) continue;

                TimeSpan difference = (lineData.Time - targetTime).Duration();
                if (difference < minDifference) {
                    minDifference = difference;
                    closestRow = i;
                }
            }

            return closestRow;
        }


        private async Task LoadPage() {
            // 计算基于XCX.top的偏移量
            long baseOffset = currentXcx.top;
            long pageSizeBytes = RowsPerPage * BytesPerRow;
            long offset = baseOffset + currentPage * pageSizeBytes;

            // 确保不超过XCX.bottom
            long maxAllowedOffset = currentXcx.bottom - pageSizeBytes;
            offset = Math.Min(offset, maxAllowedOffset);
            offset = Math.Max(offset, baseOffset);

            int bytesToRead = (int)Math.Min(
                pageSizeBytes,
                currentXcx.bottom - offset
            );

            // 读取数据并解析
            byte[] buffer = await ReadWithRetry(offset, bytesToRead);
            List<LineData> lines = ParseData(buffer, offset);

            // 使用TaskCompletionSource等待数据绑定完成
            var tcs = new TaskCompletionSource<bool>();

            // 使用具名方法替代匿名方法
            void Handler(object s, EventArgs e) {
                dgv.DataBindingComplete -= Handler;
                tcs.SetResult(true);
            }

            dgv.DataBindingComplete += Handler;

            try {
                // 设置数据源（这会触发DataBindingComplete事件）
                dgv.DataSource = new BindingList<LineData>(lines);

                // 等待数据绑定完成或超时（5秒）
                var completedTask = await Task.WhenAny(
                    tcs.Task,
                    Task.Delay(5000)
                );

                if (completedTask != tcs.Task) {
                    throw new TimeoutException("数据绑定操作超时");
                }
            } finally {
                // 确保事件处理器被移除
                dgv.DataBindingComplete -= Handler;
            }
        }


        private async void btnMEM_move_to_REC_PTR_Click(object sender, EventArgs e1) {
            try {
                var dicAddress = LoadAddress();
                long address = Convert.ToInt32(dicAddress["QUE_REC_PTR"], 16);
                byte[] buffer = new byte[2];

                using (var mmf = MemoryMappedFile.CreateFromFile(fn_hex_source, FileMode.Open))
                using (var accessor = mmf.CreateViewAccessor(address, 2, MemoryMappedFileAccess.Read)) {
                    // 检查文件长度是否足够
                    if (address + 2 > new FileInfo(fn_hex_source).Length) {
                        MessageBox.Show("地址超出文件范围！");
                        return;
                    }

                    accessor.ReadArray(0, buffer, 0, 2);
                }

                long val = BitConverter.ToInt16(buffer, 0);
                long page_size = RowsPerPage * BytesPerRow;
                currentPage = val / page_size;
                int rowIndex = (int)((val % page_size) / BytesPerRow);

                // 等待页面加载和数据绑定完成
                await LoadPage();

                // 确保UI线程更新
                if (dgv.InvokeRequired) {
                    dgv.Invoke(new Action(() => SelectRow(rowIndex)));
                } else {
                    SelectRow(rowIndex);
                }

                // 强制刷新UI
                dgv.Refresh();
            } catch (Exception ex) {
                MessageBox.Show($"操作失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }


        void SelectRow(int rowIndex) {
            if (dgv == null || dgv.Rows.Count == 0) return;

            // 计算有效行数（排除新行占位符）
            int actualRowCount = dgv.AllowUserToAddRows
                ? dgv.Rows.Count - 1
                : dgv.Rows.Count;

            if (rowIndex < 0 || rowIndex >= actualRowCount) return;

            // 清除所有行的"->"标记
            foreach (DataGridViewRow row in dgv.Rows) {
                if (!row.IsNewRow && row.Cells.Count > 0) {
                    string cellValue = row.Cells[0].Value?.ToString() ?? "";
                    if (cellValue.EndsWith("->")) {
                        row.Cells[0].Value = cellValue.Substring(0, cellValue.Length - 2);
                    }
                }
            }

            // 在目标行添加"->"标记
            if (dgv.Rows[rowIndex].Cells.Count > 0) {
                string currentValue = dgv.Rows[rowIndex].Cells[0].Value?.ToString() ?? "";
                dgv.Rows[rowIndex].Cells[0].Value = currentValue + "->";
            }

            // 设置选择模式并选中行
            //dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            dgv.ClearSelection();
            dgv.Rows[rowIndex].Selected = true;
            dgv.FirstDisplayedScrollingRowIndex = rowIndex;

            //// 设置当前单元格（可选）
            //if (dataGridView.Columns.Count > 0) {
            //    dataGridView.CurrentCell = dataGridView.Rows[rowIndex].Cells[0];
            //}

            // 修复焦点问题：设置当前单元格到可编辑列
            if (dgv.Columns.Count > 0) {
                // 找到第一个可显示的可见列
                DataGridViewColumn firstVisibleColumn = dgv.Columns
                    .Cast<DataGridViewColumn>()
                    .FirstOrDefault(c => c.Visible && c.DisplayIndex >= 0);

                if (firstVisibleColumn != null) {
                    // 设置当前单元格但不激活编辑模式
                    dgv.CurrentCell = dgv.Rows[rowIndex].Cells[firstVisibleColumn.Index];
                    dgv.BeginEdit(false); // 取消编辑模式
                }
            }

            // 强制刷新焦点
            dgv.Focus();
        }


        private async void cmbXCX_SelectedIndexChanged(object sender, EventArgs e) {
            if (memory_type != Ini.M_MASS) return;

            int iXcx;
            try {
                // 获取新选择的XCX信息
                iXcx = cmbXCX.SelectedIndex;
                if (iXcx < 0 || iXcx >= Xme.Xcx.Length) return;

                // 更新当前XCX范围
                currentXcx = Xme.Xcx[iXcx];

                // 重置分页参数
                currentPage = 0;

                // 重新初始化文件信息（包含范围验证）
                await InitializeFileInfo();

                // 加载新范围的第一页
                await LoadPage();

                // 强制界面刷新
                dgv.Refresh();

                // 新增焦点转移代码
                if (!dgv.Focused) {
                    dgv.Focus();
                }
            } catch (Exception ex) {
                MessageBox.Show($"切换存储区失败: {ex.Message}", "错误",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }


        //读取当前时间
        private void btnRefresh_Click(object sender, EventArgs e) {
            CInfo cInfo = new CInfo();

            arg[INST_BITS] = "0003";
            arg[INST_OP] = "OP_RD_INS";
            arg[INST_CMFG] = "";
            arg[INST_INSTANT] = "";
            
            Msg.setInfo_bits(ref cInfo, arg[INST_BITS]);

            cInfo.sOpArgs = arg[INST_OP] + "," + arg[INST_CMFG] + "," + arg[INST_INSTANT];
            string wr_kvs = "";

            TConsole.sendAsProtocol(xport, ref cInfo, wr_kvs, "cobra");
        }
    }
}
